"""日志配置模块，使用 loguru 进行日志管理。

本模块提供统一的日志配置，支持：
- 按日期分割日志文件
- 东八区时间记录
- 请求日志记录（IP、路由、状态等）
- 多种日志级别
"""

import os
import sys
from datetime import datetime
from typing import Optional

from loguru import logger
from fastapi import Request, Response
from starlette.middleware.base import BaseHTTPMiddleware

# 导入配置，避免循环导入
try:
    from config import settings
except ImportError:
    # 如果无法导入设置，使用默认值
    class DefaultSettings:
        log_level = "INFO"
        log_retention_days = 30
        log_timezone = "Asia/Shanghai"
    
    settings = DefaultSettings()


# 全局变量，防止重复初始化日志系统
_logger_initialized = False


class LogConfig:
    """日志配置类。"""
    
    # 日志目录
    LOG_DIR = "logs"
    
    # 统一的日志格式
    LOG_FORMAT = (
        "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
        "<level>{level: <8}</level> | "
        "<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | "
        "<level>{message}</level>"
    )


def setup_logger():
    """设置日志配置。
    
    配置日志输出到控制台和文件，支持按日期分割日志文件。
    使用东八区时间进行日志记录。
    所有日志（应用日志、请求日志、错误日志）统一存储在一个文件中。
    
    使用全局变量防止重复初始化。
    """
    global _logger_initialized
    
    # 如果已经初始化过，直接返回
    if _logger_initialized:
        return
    
    # 移除默认的控制台处理器
    logger.remove()
    
    # 配置时区为东八区
    import time
    os.environ["TZ"] = settings.log_timezone
    if hasattr(time, "tzset"):
        time.tzset()
    
    # 创建日志目录，确保权限正确
    if not os.path.exists(LogConfig.LOG_DIR):
        os.makedirs(LogConfig.LOG_DIR, mode=0o755)
        print(f"创建日志目录: {LogConfig.LOG_DIR}")
    
    # 确保日志目录可写
    if not os.access(LogConfig.LOG_DIR, os.W_OK):
        print(f"警告: 日志目录 {LogConfig.LOG_DIR} 不可写，尝试修复权限...")
        try:
            os.chmod(LogConfig.LOG_DIR, 0o755)
        except PermissionError:
            print(f"无法修复日志目录权限，请检查 {LogConfig.LOG_DIR} 的权限设置")
    
    # 添加控制台日志处理器
    logger.add(
        sys.stdout,
        format=LogConfig.LOG_FORMAT,
        level=settings.log_level,
        colorize=True,
        backtrace=True,
        diagnose=True
    )
    
    # 统一的日志文件处理器 - 所有日志都写入同一个文件
    logger.add(
        os.path.join(LogConfig.LOG_DIR, "app_{time:YYYY-MM-DD}.log"),
        format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | {message}",
        level="DEBUG",
        rotation="00:00",  # 每天午夜分割
        retention=f"{settings.log_retention_days} days",
        compression="zip",  # 压缩旧日志
        encoding="utf-8",
        backtrace=True,
        diagnose=True
    )
    
    logger.info("日志系统初始化完成，时区设置为东八区 (UTC+8)")
    
    # 标记为已初始化
    _logger_initialized = True


class LoggingMiddleware(BaseHTTPMiddleware):
    """请求日志中间件。
    
    记录每个HTTP请求的详细信息，包括：
    - 客户端IP地址
    - 请求方法和路径
    - 响应状态码
    - 请求处理时间
    """
    
    async def dispatch(self, request: Request, call_next):
        """处理请求并记录日志。
        
        Args:
            request: FastAPI 请求对象
            call_next: 下一个中间件或路由处理器
            
        Returns:
            Response: HTTP 响应对象
        """
        # 记录请求开始时间
        start_time = datetime.now()
        
        # 获取客户端IP地址
        client_ip = self._get_client_ip(request)
        
        # 执行请求
        response = await call_next(request)
        
        # 计算请求处理时间
        end_time = datetime.now()
        duration = int((end_time - start_time).total_seconds() * 1000)
        
        # 记录请求日志
        self._log_request(
            client_ip=client_ip,
            method=request.method,
            path=str(request.url.path),
            query_params=str(request.url.query) if request.url.query else "",
            status_code=response.status_code,
            duration=duration
        )
        
        return response
    
    def _get_client_ip(self, request: Request) -> str:
        """获取客户端真实IP地址。
        
        优先检查 X-Forwarded-For 和 X-Real-IP 头部，
        以支持反向代理场景。
        
        Args:
            request: FastAPI 请求对象
            
        Returns:
            str: 客户端IP地址
        """
        # 检查 X-Forwarded-For 头部（支持多级代理）
        x_forwarded_for = request.headers.get("X-Forwarded-For")
        if x_forwarded_for:
            # 取第一个IP地址（原始客户端IP）
            return x_forwarded_for.split(",")[0].strip()
        
        # 检查 X-Real-IP 头部
        x_real_ip = request.headers.get("X-Real-IP")
        if x_real_ip:
            return x_real_ip.strip()
        
        # 使用连接IP地址作为备选
        if hasattr(request.client, "host"):
            return request.client.host
        
        return "unknown"
    
    def _log_request(
        self,
        client_ip: str,
        method: str,
        path: str,
        query_params: str,
        status_code: int,
        duration: int
    ):
        """记录请求日志。
        
        Args:
            client_ip: 客户端IP地址
            method: HTTP方法
            path: 请求路径
            query_params: 查询参数
            status_code: 响应状态码
            duration: 请求处理时间（毫秒）
        """
        # 构建完整的请求路径
        full_path = f"{path}?{query_params}" if query_params else path
        
        # 根据状态码确定日志级别
        if status_code >= 500:
            log_level = "ERROR"
        elif status_code >= 400:
            log_level = "WARNING"
        else:
            log_level = "INFO"
        
        # 构建日志消息
        message = f"{method} {full_path}"
        
        # 记录请求日志 - 使用统一格式
        log_message = f"REQUEST | IP: {client_ip} | Method: {method} | Path: {full_path} | Status: {status_code} | Duration: {duration}ms"
        logger.log(log_level, log_message)


def get_logger(name: Optional[str] = None):
    """获取日志记录器实例。
    
    Args:
        name: 日志记录器名称，默认为调用模块名
        
    Returns:
        Logger: loguru 日志记录器实例
    """
    if name:
        return logger.bind(name=name)
    return logger


# 导出常用的日志记录器
app_logger = get_logger("app")
request_logger = get_logger("request")
